package com.xishu.controller;

import com.xishu.annotation.valid.MethodValidator;
import com.xishu.bo.CustomerCatalogItemMapping;
import com.xishu.entity.shop.Catalog;
import com.xishu.entity.shop.CatalogItemMapping;
import com.xishu.entity.shop.Item;
import com.xishu.entity.shop.Scene;
import com.xishu.response.ResponseData;
import com.xishu.response.VerifyUtil;
import com.xishu.service.*;
import com.xishu.util.Tools;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Api(description = "品类和菜品的映射关系")
@RestController
public class CatalogItemMappingController implements Tools {
    private static Logger logger = LoggerFactory.getLogger(CatalogItemMappingController.class);

    private CommonService commonService = CommonService.getInstance();
    private MappingService mappingService = MappingService.getInstance();
    private ItemService itemService = ItemService.getInstance();
    private CatalogService catalogService = CatalogService.getInstance();

    @ApiOperation(value = "创建品类和菜品的映射关系")
    @PostMapping(value = ("/user/catalog/item/mapping"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(companyUser = true)
    public ResponseData create(@RequestBody CatalogItemMapping catalogItemMapping) throws Exception {
        Long itemId = catalogItemMapping.getItemId();
        Long catalogId = catalogItemMapping.getCatalogId();
        VerifyUtil.verify(() -> itemId != null);
        VerifyUtil.verify(() -> catalogId != null);

        if (catalogItemMapping.getOnline() == null) {
            catalogItemMapping.setOnline(true);
        }

        //添加shop id
        Item item = ItemService.getInstance().findItem(itemId);
        catalogItemMapping.setShopId(item.getShopId());

        CatalogItemService.getInstantce().createCatalogMapping(catalogItemMapping);
        MappingService.getInstance().createCatalogItemMapping(catalogItemMapping);
        ItemService.getInstance().itemNameSyncToOther(itemId);
        CatalogService.getInstance().catalogNameSyncToOthers(catalogId);
        return ResponseData.emptyResponse();
    }

    @ApiOperation(value = "查询品类和菜品的映射关系")
    @PutMapping(value = ("/user/catalog/item/mapping"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData search(@RequestBody CatalogItemMapping catalogItemMapping) throws Exception {
        return CommonService.getInstance().searchResponse(catalogItemMapping, (mapping -> {
            //每次均直接再查询数据库或者缓存，牺牲一点性能，换来数据的一致性
            Long itemId = mapping.getItemId();
            Item item = null;

            try {
                //将菜品的数据复制到映射关系里面
                item = itemService.findItem(itemId);
                //如果有余量，那么设置余量
                if (item.getLeftCount() != null) {
                    mapping.setLeftCountShow(item.getLeftCount() + "");
                } else {
                    mapping.setLeftCountShow("");
                }

                mapping.setItemName(item.getName());
                mapping.setItemName_zh(item.getName_zh());
                mapping.setItemName_en(item.getName_en());
                mapping.setImgId(item.getImgId());
                mapping.setCatalogName(item.getCatalogName());
                mapping.setCatalogName_zh(item.getCatalogName_zh());
                mapping.setCatalogName_en(item.getCatalogName_en());
                mapping.setOnline(item.getOnline());
                mapping.setSaleOut(item.getSaleOut());
                mapping.setSetMenu(item.getSetMenu());
                mapping.setShopId(item.getShopId());
                mapping.setLeftCount(item.getLeftCount());

                //如果要查询菜品，
                if (getBoolean(mapping.getQueryItem())) {
                    logger.info("will query real time price");
                    itemService.setRealTimePrice(item);
                    mapping.setItem(item);
                } else {
                    logger.info("do not query real time price");
                }
            } catch (Exception e) {
                logger.error("e", e);
            }
        }), (catalogItemMappingList) -> {
            if (isEmpty(catalogItemMappingList)) {
                logger.info("item list is empty");
                return catalogItemMappingList;
            }

            //返回回来的集合是不可以修改的
            catalogItemMappingList = new ArrayList<>(catalogItemMappingList);

            //先排序
            itemService.sortItem(catalogItemMappingList);

            if (catalogItemMapping.getFilterSceneId() == null) {
                logger.info("do not have filter scene id");
                return CatalogItemService.getInstantce().filterValidateMapping(catalogItemMappingList);
            }

            List<Item> itemList = getItemList(catalogItemMapping, catalogItemMappingList);
            List<Long> itemIdList = itemList.stream().map(item -> item.getId()).collect(Collectors.toList());

            List<Item> filterItemSceneList = itemService.filterItemSceneList(catalogItemMapping.getFilterSceneId(), itemList);
            logger.info("filterItemSceneList size is {}, filter sceneId is {}", filterItemSceneList.size(), catalogItemMapping.getFilterSceneId());
            List<Long> filterItemIdList = filterItemSceneList.stream().map(p -> p.getId()).collect(Collectors.toList());
            //过滤出包含了该菜品的映射关系
            catalogItemMappingList = catalogItemMappingList.stream().filter(p -> filterItemIdList.contains(p.getItemId().longValue())).collect(Collectors.toList());
            //过滤存在的菜品
            catalogItemMappingList = catalogItemMappingList.stream().filter(p -> itemIdList.contains(p.getItemId().longValue())).collect(Collectors.toList());

            return CatalogItemService.getInstantce().filterValidateMapping(catalogItemMappingList);
        });
    }

    private List<Item> getItemList(CatalogItemMapping catalogItemMapping, List<CatalogItemMapping> catalogItemMappingList) {
        List<Item> itemList;

        //上面已经搜索过了
        if (getBoolean(catalogItemMapping.getQueryItem())) {
            itemList = catalogItemMappingList.stream().map(p -> p.getItem())
                    .filter(item -> !getBoolean(item.getFlagDelete())).
                            collect(Collectors.toList());
            logger.info("after query item list size is {}", itemList.size());
        } else {
            List<Long> itemIdList = catalogItemMappingList.stream().map(p -> p.getItemId()).collect(Collectors.toList());
            //过滤没有删除掉的菜品
            itemList = itemService.findItemByItemList(itemIdList)
                    .stream().filter(item -> !getBoolean(item.getFlagDelete()))
                    .collect(Collectors.toList());
            logger.info("after query item list size is {}", itemList.size());
        }
        return itemList;
    }

    @ApiOperation(value = "删除品类和菜品的映射关系")
    @DeleteMapping(value = ("/user/catalog/item/mapping"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(companyUser = true)
    public ResponseData delete(@RequestBody CatalogItemMapping catalogItemMapping) throws Exception {
        return CommonService.getInstance().delete(catalogItemMapping);
    }

    //// TODO: 2022/8/4
    @ApiOperation(value = "查询该商铺下面的所有菜的映射")
    @PutMapping(value = ("/user/catalog/item/mapping/shop"), produces = ("application/json;charset=UTF-8"))
    @MethodValidator(mustLogin = false)
    public ResponseData searchAllInShop(@RequestBody CatalogItemMapping catalogItemMapping) throws Exception {
        ArrayList<CustomerCatalogItemMapping> mappingList = new ArrayList<>();

        Long shopId = catalogItemMapping.getShopId();
        VerifyUtil.verify(() -> shopId != null);

        //查询当前场景
        Scene matchScene = SceneService.getInstance().findTheMatchScene(shopId);
        logger.info("current scene is {}", matchScene);

        List<Item> suggestionItemList = itemService.findAllSuggestionItem(shopId, true);

        //设置实时价格
        itemService.setItemListWithRealTimePrice(suggestionItemList);
        suggestionItemList = itemService.filterValidPriceItemList(suggestionItemList);
        logger.info("before filter suggestionItemList size is {}", suggestionItemList.size());
        suggestionItemList = itemService.filterItemSceneList(matchScene.getId(), suggestionItemList);
        logger.info("after filter suggestionItemList size is {}", suggestionItemList.size());

        //给推荐菜排序
        suggestionItemList.sort(Comparator.comparing(Item::getSuggestShowOrder));

        mappingList.add(new CustomerCatalogItemMapping("suggestion", suggestionItemList,0l));

        logger.info("end suggestion item deal, suggestionItemList is {}", suggestionItemList.size());

        List<Catalog> catalogList = catalogService.findCatalogByShopId(shopId);

        //排序
        catalogList.sort(Comparator.comparing(Catalog::getShowOrder));
        for (Catalog catalog : catalogList) {

            Long catalogId = catalog.getId();
            List<Item> itemList = itemService.findItemByCatalogId(catalog.getId(), true);
            logger.info("catalog {} size is {}", catalog.getName(), itemList.size());



            //品类跟场景匹配，没匹配上直接不反回该品类
            Boolean catalogMatch = catalogService.isCatalogInSceneTime(matchScene.getId(), catalog);
            if (!catalogMatch){
                logger.info("catalog {} not match scene {}",catalog.getName(),matchScene.getName());
                continue;
            }
            //设置实时价格
            itemService.setItemListWithRealTimePrice(itemList);
            itemList = itemService.filterValidPriceItemList(itemList);
            logger.info("before filter itemList size is {}", itemList.size());
            itemList = itemService.filterItemSceneList(matchScene.getId(), itemList);
            logger.info("after filter itemList size is {}", itemList.size());

            //不显示的菜隐藏掉
            itemList = itemList.stream().filter(item -> !getBoolean(item.getNotShowInC())).collect(Collectors.toList());

            //菜品排序
            itemList.sort(new Comparator<Item>() {
                @Override
                public int compare(Item o1, Item o2) {
                    return getInt(o1.getShowOrder()) - getInt(o2.getShowOrder());
                }
            });

            //如果品类匹配上场景了，但是品类里的菜没有匹配上场景的，直接不反回
            if (isEmpty(itemList)){
                logger.info("no item in catalog {} match scene {}",catalog.getName(),matchScene.getName());
                continue;
            }
            mappingList.add(new CustomerCatalogItemMapping(catalog.getName(), itemList,catalogId));
            logger.info("catalog {} size is {}", catalog.getName(), itemList.size());
        }

        logger.info("end common catalog price deal");

        return commonService.createResponse(mappingList);
    }

    @ApiOperation(value = "批量修改上下线关系")
    @PutMapping(value = ("/user/catalog/item/mapping/status"), produces = ("application/json;charset=UTF-8"))
    public ResponseData batchStatus(@RequestBody CatalogItemMapping reqCatalogItemMapping) throws Exception {
        VerifyUtil.verify(() -> isNotEmpty(reqCatalogItemMapping.getShopId()));

        if (reqCatalogItemMapping.getSaleOut() != null) {
            List<CatalogItemMapping> catalogItemMappingList = null;
            boolean saleOut = getBoolean(reqCatalogItemMapping.getSaleOut());

            if (isNotEmpty(reqCatalogItemMapping.getCatalogId())) {
                catalogItemMappingList = mappingService.findCatalogItemMappingByCatalog(reqCatalogItemMapping.getCatalogId());
                //售罄只处理已上架的菜
                catalogItemMappingList = catalogItemMappingList.stream().filter(s -> getBoolean(s.getOnline())).collect(Collectors.toList());
                for (CatalogItemMapping catalogItemMapping : catalogItemMappingList) {
                    Item item = new Item();
                    item.setSaleOut(reqCatalogItemMapping.getSaleOut());
                    item.setId(catalogItemMapping.getItemId());
                    item.setFlagDelete(false);
                    new ItemController().modify(item);
                }
            } else {
                List<Item> allSuggestionItem = itemService.findAllSuggestionItem(reqCatalogItemMapping.getShopId(), true);
                for (Item item : allSuggestionItem) {
                    Item itemModify = new Item();
                    itemModify.setId(item.getId());
                    itemModify.setSaleOut(reqCatalogItemMapping.getSaleOut());
                    itemModify.setFlagDelete(false);
                    new ItemController().modify(itemModify);
                }
            }

            return ResponseData.emptyResponse();
        }

        if (isNotEmpty(reqCatalogItemMapping.getCatalogId())) {
            List<CatalogItemMapping> catalogItemMappingList = mappingService.findCatalogItemMappingByCatalog(reqCatalogItemMapping.getCatalogId());

            for (CatalogItemMapping catalogItemMapping : catalogItemMappingList) {
                //修改映射上下线
                if (reqCatalogItemMapping.getOnline() != null) {
                    logger.info("will set item online {}", reqCatalogItemMapping.getOnline());
                    catalogItemMapping.setOnline(getBoolean(reqCatalogItemMapping.getOnline()));
                }

                //修改已售完
                if (reqCatalogItemMapping.getSaleOut() != null) {
                    logger.info("will set mapping sale out", reqCatalogItemMapping.getSaleOut());
                    catalogItemMapping.setSaleOut(reqCatalogItemMapping.getSaleOut());
                }

                commonService.directSave(catalogItemMapping);

                //修改单个菜品的上下线
                Item item = itemService.findItem(catalogItemMapping.getItemId());
                if (reqCatalogItemMapping.getOnline() != null) {
                    logger.info("will set mapping online {}", reqCatalogItemMapping.getOnline());
                    item.setOnline(reqCatalogItemMapping.getOnline());
                }

                //修改修改单个菜品已售完
                if (reqCatalogItemMapping.getSaleOut() != null) {
                    logger.info("will set mapping sale out {}", reqCatalogItemMapping.getSaleOut());
                    item.setSaleOut(reqCatalogItemMapping.getSaleOut());

                    //如果是单个售罄了，那么修改相关的菜的售罄
                    if (getBoolean(reqCatalogItemMapping.getSaleOut())) {
                        itemService.setSetMenuSaleOut(item);
                    } else {
                        itemService.restoreSetMenuSaleOut(item);
                    }

                    //如果是单个恢复售罄，那么恢复单个菜的售罄
                }

                commonService.directSave(item);
            }

            return ResponseData.emptyResponse();
        } else {
            //套餐或者推荐菜上下线
            Item item = new Item();
            item.setShopId(reqCatalogItemMapping.getShopId());

            if (reqCatalogItemMapping.getSetMenu() != null) {
                logger.info("will set setMenu");
                item.setSetMenu(reqCatalogItemMapping.getSetMenu());
            }

            if (reqCatalogItemMapping.getSuggestion() != null) {
                logger.info("will set suggestion");
                item.setSuggestion(reqCatalogItemMapping.getSuggestion());
            }

            List<Item> itemList = commonService.searchAll(item);

            for (Item tempItem : itemList) {
                logger.info("will modify item {}", tempItem);
                if (reqCatalogItemMapping.getOnline() != null) {
                    logger.info("will set online {}", reqCatalogItemMapping.getOnline());
                    tempItem.setOnline(reqCatalogItemMapping.getOnline());
                }

                if (reqCatalogItemMapping.getSaleOut() != null) {
                    logger.info("will set sale out {}", reqCatalogItemMapping.getSaleOut());
                    tempItem.setSaleOut(reqCatalogItemMapping.getSaleOut());
                }

                commonService.directSave(tempItem);

                //同步修改映射里面的关系
                CatalogItemMapping catalogItemMapping = mappingService.findCatalogItemMapping(tempItem.getId());

                if (catalogItemMapping != null) {
                    if (reqCatalogItemMapping.getOnline() != null) {
                        logger.info("will set mapping online {}", reqCatalogItemMapping.getOnline());
                        catalogItemMapping.setOnline(reqCatalogItemMapping.getOnline());
                    }

                    if (reqCatalogItemMapping.getSaleOut() != null) {
                        logger.info("will set mapping sale out {}", reqCatalogItemMapping.getSaleOut());
                        catalogItemMapping.setSaleOut(reqCatalogItemMapping.getSaleOut());
                    }

                    commonService.directSave(catalogItemMapping);
                }
            }

            return ResponseData.emptyResponse();
        }

    }
}
